/*
 * This program is free software: you can redistribute it and/or modify it under the terms of the 
 * GNU Affero General Public License as published by the Free Software Foundation, either version 3 
 * of the License, or (at your option) any later version.
 * 
 * In accordance with Section 7(b) of the GNU Affero General Public License version 3, 
 * the Appropriate Legal Notices must display the following words on all interactive user interfaces: 
 * "Copyright (C) 2005-2011 SplendidCRM Software, Inc. All rights reserved."
 */
 
var sPRODUCT_TITLE  = 'SplendidCRM';
var sSTARTUP_MODULE = 'Contacts';
var bWINDOWS_AUTH   = false;

function LoginViewUI_UpdateHeader(sLayoutPanel, sActionsPanel, bShow)
{
	try
	{
		var bgPage = chrome.extension.getBackgroundPage();
		var divHeader_divAuthenticated   = document.getElementById('divHeader_divAuthenticated'  );
		var divHeader_spnWelcome         = document.getElementById('divHeader_spnWelcome'        );
		var divHeader_spnUserName        = document.getElementById('divHeader_spnUserName'       );
		var divHeader_spnLogout          = document.getElementById('divHeader_spnLogout'         );
		var divHeader_lnkLogout          = document.getElementById('divHeader_lnkLogout'         );
		var divHeader_divOnlineStatus    = document.getElementById('divHeader_divOnlineStatus'   );
		var divHeader_OfflineCache       = document.getElementById('divHeader_OfflineCache'      );
		var divHeader_divSplendidStorage = document.getElementById('divHeader_divSplendidStorage');
		divHeader_divAuthenticated.style.display = (bShow ? 'inline'                  : 'none');
		divHeader_spnWelcome.innerHTML           = (bShow ? L10n.Term('.NTC_WELCOME') : '');
		divHeader_spnUserName.innerHTML          = (bShow ? (sUSER_NAME + ' ' + sTEAM_NAME) : '');
		divHeader_lnkLogout.innerHTML            = (bShow ? L10n.Term('.LBL_LOGOUT' ) : '');
		divHeader_spnLogout.style.display        = (bWINDOWS_AUTH ? 'none' : 'inline');
		divHeader_divOnlineStatus.innerHTML      =  bgPage.GetIsOffline() ? L10n.Term('.LBL_OFFLINE') : L10n.Term('.LBL_ONLINE');
		divHeader_lnkLogout.onclick = function()
		{
			LoginViewUI_PageCommand(sLayoutPanel, sActionsPanel, 'Logout', null, null);
		};
		if ( divHeader_divSplendidStorage != null )
		{
			divHeader_divSplendidStorage.style.display = (bShow ? 'inline' : 'none');
		}
		
		if ( bgPage.SplendidStorage !== undefined && bgPage.SplendidStorage.db != null )
		{
			divHeader_divOnlineStatus.innerHTML += ' Web SQL';
		}
		
		if ( divHeader_OfflineCache != null )
		{
			if ( divHeader_OfflineCache.childNodes != null )
			{
				while ( divHeader_OfflineCache.childNodes.length > 0 )
				{
					divHeader_OfflineCache.removeChild(divHeader_OfflineCache.firstChild);
				}
			}
			divHeader_OfflineCache.style.display = 'none';
			// 10/19/2011 Paul.  IE6 does not support localStorage. 
			// 12/08/2011 Paul.  IE7 defines window.XMLHttpRequest but not window.localStorage. 
			if ( window.localStorage && localStorage['OFFLINE_CACHE'] != null )
			{
				var arrOFFLINE_CACHE = JSON.parse(localStorage['OFFLINE_CACHE']);
				//alert(dumpObj(arrOFFLINE_CACHE, 'arrOFFLINE_CACHE'));
				// 10/07/2011 Paul.  arrOFFLINE_CACHE.length is not valid. 
				var nOFFLINE_CACHE_length = 0;
				for ( var key in arrOFFLINE_CACHE )
				{
					nOFFLINE_CACHE_length++;
				}
				
				divHeader_OfflineCache.style.display = (bShow && nOFFLINE_CACHE_length > 0) ? 'inline' : 'none';
				
				var divSubmit = document.createElement('div');
				divHeader_OfflineCache.appendChild(divSubmit);
				var btnSubmit = document.createElement('input');
				btnSubmit.type      = 'submit';
				btnSubmit.value     = L10n.Term('.LBL_SUBMIT_BUTTON_LABEL');
				btnSubmit.title     = L10n.Term('.LBL_SUBMIT_BUTTON_LABEL');
				btnSubmit.className = 'button';
				btnSubmit.onclick   = function()
				{
					EditViewUI_SubmitOffline(sLayoutPanel, sActionsPanel);
				}
				divSubmit.appendChild(btnSubmit);
				divSubmit.style.display = (bShow && !bgPage.GetIsOffline() && nOFFLINE_CACHE_length > 0) ? 'inline' : 'none';

				for ( var key in arrOFFLINE_CACHE )
				{
					var oCached = arrOFFLINE_CACHE[key];
					var divItem = document.createElement('div');
					divHeader_OfflineCache.appendChild(divItem);
					
					var sModuleLabel = L10n.Term('.moduleList.' + oCached.MODULE_NAME);
					if ( Right(sModuleLabel, 3) == 'ies' && sModuleLabel.length > 3 )
						sModuleLabel = sModuleLabel.substring(0, sModuleLabel.length - 3) + 'y';
					else if ( Right(sModuleLabel, 1) == 's' )
						sModuleLabel = sModuleLabel.substring(0, sModuleLabel.length - 1);
					
					var aView = document.createElement('a');
					divItem.appendChild(aView);
					aView.href      = 'javascript:DetailViewUI_Load("' + sLayoutPanel + '", "' + sActionsPanel + '", "' + oCached.MODULE_NAME + '", "' + oCached.ID + '")';
					
					/*
					var imgView = document.createElement('img');
					aView.appendChild(imgView);
					imgView.align       = 'absmiddle';
					imgView.height      = 16;
					imgView.width       = 16;
					imgView.borderWidth = 0;
					imgView.src         = sIMAGE_SERVER + 'App_Themes/Six/images/view_inline.gif';
					imgView.alt         = L10n.Term('.LNK_VIEW');
					imgView.style.padding = '2';
					imgView.style.border  = 'none';
					*/

					var spnItem = document.createElement('span');
					aView.appendChild(spnItem);
					spnItem.innerHTML = sModuleLabel + ': ' + oCached.NAME;
					spnItem.style.padding = '2';
				}
			}
		}
	}
	catch(e)
	{
		SplendidError.SystemAlert(e, 'LoginViewUI_UpdateHeader');
	}
}

function LoginViewUI_ClearModuleLists(callback)
{
	var arrKeys = new Array();
	var bgPage = chrome.extension.getBackgroundPage();
	bgPage.SplendidStorage.foreach(function(status, key, value)
	{
		if ( status == 1 )
		{
			// 11/28/2011 Paul.  Remove module lists, but not the default. 
			if ( key.indexOf('Rest.svc/GetModuleList?') > 0 && Right(key, '$filter=') )
			{
				arrKeys.push(key);
			}
		}
		else if ( status == 0 )
		{
			while ( arrKeys.length > 0 )
			{
				var key = arrKeys.pop();
				SplendidStorage.removeItem(key);
				SplendidError.SystemLog('Removed item from cache: ' + key);
			}
			if ( callback )
			{
				callback(0, '');
			}
		}
	});
}

function LoginViewUI_PageCommand(sLayoutPanel, sActionsPanel, sCommandName, sCommandArguments, cbLoginComplete)
{
	try
	{
		if ( sCommandName == 'Login' )
		{
			var txtUSER_NAME      = document.getElementById(sLayoutPanel + '_ctlLoginView_txtUSER_NAME'     );
			var txtPASSWORD       = document.getElementById(sLayoutPanel + '_ctlLoginView_txtPASSWORD'      );
			var chkENABLE_OFFLINE = document.getElementById(sLayoutPanel + '_ctlLoginView_chkENABLE_OFFLINE');
			sUSER_NAME = txtUSER_NAME.value;
			sPASSWORD  = txtPASSWORD.value;
			var bgPage = chrome.extension.getBackgroundPage();
			bgPage.Login(function(status, message)
			{
				var spnError = document.getElementById(sLayoutPanel + '_ctlLoginView_lblError');
				if ( status == 0 )
				{
					// 09/30/2011 Paul.  If there is no response, check against the stored values. 
					// 10/19/2011 Paul.  IE6 does not support localStorage. 
					// 11/27/2011 Paul.  The USER_NAME is not case-significant, so don't require it here either. 
					// 12/08/2011 Paul.  IE7 defines window.XMLHttpRequest but not window.localStorage. 
					if ( chkENABLE_OFFLINE.checked && window.localStorage && Sql.ToString(localStorage['USER_NAME']).toLowerCase() == sUSER_NAME.toLowerCase() && localStorage['USER_HASH'] == Sha1.hash(sPASSWORD) )
					{
						sUSER_ID          = localStorage['USER_ID'         ];
						sUSER_NAME        = localStorage['USER_NAME'       ];
						sTEAM_ID          = localStorage['TEAM_ID'         ];
						sTEAM_NAME        = localStorage['TEAM_NAME'       ];
						sUSER_LANG        = localStorage['USER_LANG'       ];
						sUSER_DATE_FORMAT = localStorage['USER_DATE_FORMAT'];
						sUSER_TIME_FORMAT = localStorage['USER_TIME_FORMAT'];
					}
					else
					{
						message = L10n.Term('Users.ERR_INVALID_PASSWORD');
						status  = -1;
					}
				}
				if ( status == 0 || status == 1 )
				{
					spnError.innerHTML = 'Login successful';
					// 09/30/2011 Paul.  Don't fetch UI files if we are offline. 
					// 11/27/2011 Paul.  bENABLE_OFFLINE is a global flag, so we cannot turn off just for UI. 
					// bENABLE_OFFLINE must remain enabled in order to retrieved cached UI data when attempting to use offline. 
					// 12/08/2011 Paul.  IE7 defines window.XMLHttpRequest but not window.localStorage. 
					bENABLE_OFFLINE = window.localStorage ? chkENABLE_OFFLINE.checked : false;
					// 10/12/2011 Paul.  If we are online, we should take this time to clear local storage.  
					// The concern is that we will be caching all searches and we need a way to clear this before the storage becomes full. 
					// 12/08/2011 Paul.  IE7 defines window.XMLHttpRequest but not window.localStorage. 
					if ( status == 1 && window.localStorage )
					{
						// 10/12/2011 Paul.  Make sure not to clear offline cached data. 
						// 10/12/2011 Paul.  For now, lets just clear module lists. 
						// 11/28/2011 Paul.  We must clear the lists, otherwise searches will eventually exhaust available memory. 
						LoginViewUI_ClearModuleLists();
					}
					
					bgPage.GetUserProfile(function(status, message)
					{
						// 10/19/2011 Paul.  IE6 does not support localStorage. 
						// 12/08/2011 Paul.  IE7 defines window.XMLHttpRequest but not window.localStorage. 
						if ( status == 1 && window.localStorage )
						{
							localStorage['USER_ID'         ] = sUSER_ID         ;
							localStorage['USER_NAME'       ] = sUSER_NAME       ;
							localStorage['TEAM_ID'         ] = sTEAM_ID         ;
							localStorage['TEAM_NAME'       ] = sTEAM_NAME       ;
							localStorage['USER_HASH'       ] = Sha1.hash(sPASSWORD);
							localStorage['USER_LANG'       ] = sUSER_LANG       ;
							localStorage['USER_DATE_FORMAT'] = sUSER_DATE_FORMAT;
							localStorage['USER_TIME_FORMAT'] = sUSER_TIME_FORMAT;
						}
						// 09/30/2011 Paul.  Clear the password for security reasons. 
						// 11/27/2011 Paul.  Clearing the password prevents automatic re-authentication when the connection is restored. 
						//sPASSWORD = '';
						// 11/28/2011 Paul.  We need to save the user name and password so that we can re-authenticate when the connection is restored. 
						// 12/08/2011 Paul.  IE7 defines window.XMLHttpRequest but not window.localStorage. 
						if ( window.sessionStorage )
						{
							sessionStorage['PASSWORD'        ] = sPASSWORD        ;
							sessionStorage['USER_ID'         ] = sUSER_ID         ;
							sessionStorage['USER_NAME'       ] = sUSER_NAME       ;
							sessionStorage['TEAM_ID'         ] = sTEAM_ID         ;
							sessionStorage['TEAM_NAME'       ] = sTEAM_NAME       ;
							sessionStorage['USER_LANG'       ] = sUSER_LANG       ;
							sessionStorage['USER_DATE_FORMAT'] = sUSER_DATE_FORMAT;
							sessionStorage['USER_TIME_FORMAT'] = sUSER_TIME_FORMAT;
						}
						
						var rowDefaultSearch = null;
						SplendidUI_Init(sLayoutPanel, sActionsPanel, sSTARTUP_MODULE, rowDefaultSearch, function(status, message)
						{
							if ( status == 1 )
							{
								LoginViewUI_UpdateHeader(sLayoutPanel, sActionsPanel, true);
								if ( bENABLE_OFFLINE )
								{
									SplendidUI_Cache(function(status, message)
									{
										if ( status == 2 )
										{
											SplendidError.SystemMessage(message);
										}
									});
								}
								if ( cbLoginComplete != null )
									cbLoginComplete(1, null);
								SplendidError.SystemMessage('');
							}
							else
							{
								SplendidError.SystemMessage(message);
							}
						});
					});
				}
				else
				{
					spnError.innerHTML = message;
				}
			});
		}
		else if ( sCommandName == 'Logout' )
		{
			var bgPage = chrome.extension.getBackgroundPage();
			bgPage.Logout(function(status, message)
			{
				try
				{
					// 11/28/2011 Paul.  We need to save the user name and password so that we can re-authenticate when the connection is restored. 
					if ( window.XMLHttpRequest )
					{
						sessionStorage.clear();
					}
					sUSER_NAME = '';
					sUSER_ID   = '';
					// 10/15/2011 Paul.  sTabMenuCtl is a div tag now so that we can do more with the panel. 
					TabMenuUI_Clear('ctlTabMenu');
					SplendidUI_Clear(sLayoutPanel, sActionsPanel);
					LoginViewUI_Load(sLayoutPanel, sActionsPanel, null, function(status, message)
					{
					});
				}
				catch(e)
				{
					SplendidError.SystemError(e, 'LoginViewUI_PageCommand Logout()');
				}
			});
		}
		else
		{
			SplendidError.SystemMessage('LoginViewUI_PageCommand: Unknown command ' + sCommandName);
		}
	}
	catch(e)
	{
		SplendidError.SystemError(e, 'LoginViewUI_PageCommand');
	}
}

function LoginViewUI_Clear(sLayoutPanel, sActionsPanel, callback)
{
	try
	{
		var divMainLayoutPanel = document.getElementById(sLayoutPanel);
		if ( divMainLayoutPanel != null && divMainLayoutPanel.childNodes != null )
		{
			while ( divMainLayoutPanel.childNodes.length > 0 )
			{
				divMainLayoutPanel.removeChild(divMainLayoutPanel.firstChild);
			}
		}
		var divMainActionsPanel = document.getElementById(sActionsPanel);
		if ( divMainActionsPanel != null && divMainActionsPanel.childNodes != null )
		{
			while ( divMainActionsPanel.childNodes.length > 0 )
			{
				divMainActionsPanel.removeChild(divMainActionsPanel.firstChild);
			}
		}
		LoginViewUI_UpdateHeader(sLayoutPanel, sActionsPanel, false);
		callback(1, null);
	}
	catch(e)
	{
		callback(-1, SplendidError.FormatError(e, 'LoginViewUI_Clear'));
	}
}

function LoginViewUI_LoadView(sLayoutPanel, sActionsPanel, cbLoginComplete, callback)
{
	try
	{
		var divMainLayoutPanel = document.getElementById(sLayoutPanel);
		var divSpacer = document.createElement('div');
		divSpacer.style.height = '40px';
		divMainLayoutPanel.appendChild(divSpacer);

		//<table class="ModuleActionsShadingTable" cellspacing="0" cellpadding="0" align="Center" border="0" style="border-collapse:collapse;width: 450px;">
		var tblMain = document.createElement('table');
		tblMain.id          = sLayoutPanel + '_ctlLoginView_tblMain';
		// 09/25/2011 Paul.  Shrink the table so that it will fit within an Office Extension. 
		tblMain.style.width = '380px';
		tblMain.className   = 'ModuleActionsShadingTable';
		tblMain.cellSpacing = 0;
		tblMain.cellPadding = 0;
		tblMain.border      = 0;
		tblMain.align       = 'Center';
		tblMain.style.borderCollapse = 'collapse';
		divMainLayoutPanel.appendChild(tblMain);
		
		// 09/25/2011 Paul.  Internet Explorer requires tbody when using the DOM to add tr and td elements. 
		var tbody = document.createElement('tbody');
		tblMain.appendChild(tbody);

		// <tr><td class="ModuleActionsShadingHorizontal" colspan="3"></td></tr>
		var tr = document.createElement('tr');
		tbody.appendChild(tr);
		var td = document.createElement('td');
		tr.appendChild(td);
		td.className = 'ModuleActionsShadingHorizontal';
		td.colSpan   = 3;

		// <td class="ModuleActionsShadingVertical"></td>
		tr = document.createElement('tr');
		tbody.appendChild(tr);
		td = document.createElement('td');
		tr.appendChild(td);
		td.className = 'ModuleActionsShadingVertical';

		// <table class="ModuleActionsInnerTable" cellspacing="0" cellpadding="0" align="Center" border="0" style="width:100%;border-collapse:collapse;">
		var tblInner = document.createElement('table');
		tblInner.width       = '100%';
		tblInner.className   = 'ModuleActionsInnerTable';
		tblInner.cellSpacing = 0;
		tblInner.cellPadding = 0;
		tblInner.border      = 0;
		tblInner.align       = 'Center';
		tblInner.style.borderCollapse = 'collapse';
		td = document.createElement('td');
		tr.appendChild(td);
		td.appendChild(tblInner);

		var tbodyInner = document.createElement('tbody');
		tblInner.appendChild(tbodyInner);
		var trInner = document.createElement('tr');
		tbodyInner.appendChild(trInner);
		var tdInner = document.createElement('td');
		trInner.appendChild(tdInner);
		// <td style="padding-top: 20px; padding-bottom: 20px; padding-left: 40px; padding-right: 40px;">
		tdInner.style.paddingTop    = 20;
		tdInner.style.paddingBottom = 20;
		tdInner.style.paddingLeft   = 40;
		tdInner.style.paddingRight  = 40;

		// <table cellspacing="2" cellpadding="0" border="0" style="border-width:0px;width:100%;">
		var tblHeader = document.createElement('table');
		tblHeader.cellSpacing = 2;
		tblHeader.cellPadding = 0;
		tblHeader.border      = 0;
		tblHeader.width       = '100%';
		tdInner.appendChild(tblHeader);

		var tbodyHeader = document.createElement('tbody');
		tblHeader.appendChild(tbodyHeader);
		var trHeader = document.createElement('tr');
		tbodyHeader.appendChild(trHeader);
		// <td style="font-family: Arial; font-size: 14pt; font-weight: bold; color: #003564;">SplendidCRM Enterprise</td>
		var tdHeader = document.createElement('td');
		tdHeader.style.fontFamily = 'Arial';
		tdHeader.style.fontSize   = '14pt';
		tdHeader.style.fontWeight = 'bold';
		tdHeader.color            = '#003564';
		trHeader.appendChild(tdHeader);
		var txt = document.createTextNode(sPRODUCT_TITLE);
		tdHeader.appendChild(txt);

		// <table id="ctlLoginView_tblUser" cellspacing="2" cellpadding="0" align="Center" border="0" style="border-width:0px;width:100%;">
		var tblUser = document.createElement('table');
		tblUser.id          = sLayoutPanel + '_ctlLoginView_tblUser';
		tblUser.cellSpacing = 2;
		tblUser.cellPadding = 0;
		tblUser.border      = 0;
		tblUser.width       = '100%';
		tblUser.align       = 'Center';
		tdInner.appendChild(tblUser);

		var tbodyUser = document.createElement('tbody');
		tblUser.appendChild(tbodyUser);
		var trUser = document.createElement('tr');
		tbodyUser.appendChild(trUser);
		// <td colspan="2" style="font-size: 12px; padding-top: 5px;"><span id="ctlLoginView_lblInstructions">Please login.</span></td>
		var tdUser = document.createElement('td');
		tdUser.colSpan          = 2;
		tdUser.style.fontFamily = 'Arial';
		tdUser.style.fontSize   = '12pt';
		//tdUser.className = 'dataLabel';
		trUser.appendChild(tdUser);
		var spn = document.createElement('span');
		spn.id = sLayoutPanel + '_ctlLoginView_lblInstructions';
		tdUser.appendChild(spn);
		txt = document.createTextNode(L10n.Term('.NTC_LOGIN_MESSAGE'));
		spn.appendChild(txt);

		trUser = document.createElement('tr');
		tbodyUser.appendChild(trUser);
		// <td colspan="2"><span id="ctlLoginView_lblError" class="error"></span></td>
		tdUser = document.createElement('td');
		tdUser.colSpan = 2;
		trUser.appendChild(tdUser);
		spn = document.createElement('span');
		spn.id        = sLayoutPanel + '_ctlLoginView_lblError';
		spn.className = 'error';
		tdUser.appendChild(spn);

		trUser = document.createElement('tr');
		tbodyUser.appendChild(trUser);
		// <td class="dataLabel" style="width:30%;">User Name:</td><td style="width:70%;"><input type="text" id="ctlLoginView_txtUSER_NAME" value="admin" style="width:180px;" /> &nbsp;</td>
		tdUserLabel = document.createElement('td');
		tdUserLabel.className = 'dataLabel';
		tdUserLabel.width     = '30%';
		trUser.appendChild(tdUserLabel);
		spn = document.createElement('span');
		spn.id        = sLayoutPanel + '_ctlLoginView_lblUserName';
		spn.className = 'dataLabel';
		tdUserLabel.appendChild(spn);
		txt = document.createTextNode(L10n.Term('Users.LBL_USER_NAME'));
		spn.appendChild(txt);
		
		var tdUserField = document.createElement('td');
		tdUserField.width = '70%';
		trUser.appendChild(tdUserField);
		var txtUSER_NAME = document.createElement('input');
		txtUSER_NAME.id    = sLayoutPanel + '_ctlLoginView_txtUSER_NAME';
		txtUSER_NAME.type  = 'text';
		txtUSER_NAME.width = 180;
		txtUSER_NAME.style.width = '180px';
		txtUSER_NAME.onkeypress = function(e)
		{
			return RegisterEnterKeyPress(e, sLayoutPanel + '_ctlLoginView_btnLogin');
		};
		tdUserField.appendChild(txtUSER_NAME);
		// 11/29/2011 Paul.  Make logins easier by recalling the last login. 
		// 12/08/2011 Paul.  IE7 defines window.XMLHttpRequest but not window.localStorage. 
		if ( window.localStorage && localStorage['USER_NAME'] !== undefined )
			txtUSER_NAME.value = localStorage['USER_NAME'];

		trUser = document.createElement('tr');
		tbodyUser.appendChild(trUser);
		// <td class="dataLabel" style="width:30%;">User Name:</td><td style="width:70%;"><input type="text" id="ctlLoginView_txtUSER_NAME" value="admin" style="width:180px;" /> &nbsp;</td>
		tdUserLabel = document.createElement('td');
		tdUserLabel.className = 'dataLabel';
		tdUserLabel.width     = '30%';
		trUser.appendChild(tdUserLabel);
		spn = document.createElement('span');
		spn.id        = sLayoutPanel + '_ctlLoginView_lblUserName';
		spn.className = 'dataLabel';
		tdUserLabel.appendChild(spn);
		txt = document.createTextNode(L10n.Term('Users.LBL_PASSWORD'));
		spn.appendChild(txt);
		
		tdUserField = document.createElement('td');
		tdUserField.width = '70%';
		trUser.appendChild(tdUserField);
		var txtPASSWORD = document.createElement('input');
		txtPASSWORD.id    = sLayoutPanel + '_ctlLoginView_txtPASSWORD';
		txtPASSWORD.type  = 'password';
		txtPASSWORD.wdith = 180;
		txtPASSWORD.style.width = '180px';
		txtPASSWORD.onkeypress = function(e)
		{
			return RegisterEnterKeyPress(e, sLayoutPanel + '_ctlLoginView_btnLogin');
		};
		tdUserField.appendChild(txtPASSWORD);

		trUser = document.createElement('tr');
		tbodyUser.appendChild(trUser);
		tdUserLabel = document.createElement('td');
		tdUserLabel.className = 'dataLabel';
		tdUserLabel.width     = '30%';
		trUser.appendChild(tdUserLabel);
		tdUserField = document.createElement('td');
		tdUserField.width = '70%';
		trUser.appendChild(tdUserField);

		var chkENABLE_OFFLINE = document.createElement('input');
		chkENABLE_OFFLINE.id        = sLayoutPanel + '_ctlLoginView_chkENABLE_OFFLINE';
		chkENABLE_OFFLINE.type      = 'checkbox';
		chkENABLE_OFFLINE.className = 'checkbox';
		tdUserField.appendChild(chkENABLE_OFFLINE);
		// 10/04/2011 Paul.  IE8 requires that we set checked after appending. 
		chkENABLE_OFFLINE.checked   = bENABLE_OFFLINE;
		var txtENABLE_OFFLINE = document.createTextNode(' ' + L10n.Term('.LBL_ENABLE_OFFLINE'));
		tdUserField.appendChild(txtENABLE_OFFLINE);

		trUser = document.createElement('tr');
		tbodyUser.appendChild(trUser);
		tdUserLabel = document.createElement('td');
		tdUserLabel.className = 'dataLabel';
		tdUserLabel.width     = '30%';
		trUser.appendChild(tdUserLabel);
		tdUserField = document.createElement('td');
		tdUserField.width = '70%';
		trUser.appendChild(tdUserField);

		var btnLogin = document.createElement('input');
		btnLogin.id        = sLayoutPanel + '_ctlLoginView_btnLogin';
		btnLogin.type      = 'submit';
		btnLogin.className = 'button';
		btnLogin.value     = L10n.Term('Users.LBL_LOGIN_BUTTON_LABEL');
		btnLogin.title     = btnLogin.value;
		btnLogin.onclick   = function()
		{
			LoginViewUI_PageCommand(sLayoutPanel, sActionsPanel, 'Login', null, cbLoginComplete);
		};
		tdUserField.appendChild(btnLogin);

		// <td class="ModuleActionsShadingVertical"></td>
		td = document.createElement('td');
		tr.appendChild(td);
		td.className = 'ModuleActionsShadingVertical';

		// <tr><td class="ModuleActionsShadingHorizontal" colspan="3"></td></tr>
		tr = document.createElement('tr');
		tbody.appendChild(tr);
		td = document.createElement('td');
		tr.appendChild(td);
		td.className = 'ModuleActionsShadingHorizontal';
		td.colSpan   = 3;

		divSpacer = document.createElement('div');
		divSpacer.style.height = '40px';
		divMainLayoutPanel.appendChild(divSpacer);

		// <asp:Table Width="100%" BorderWidth="0" CellPadding="0" CellSpacing="0" runat="server">
		var tblCopyright = document.createElement('table');
		tblCopyright.width       = '100%';
		tblCopyright.cellSpacing = 0;
		tblCopyright.cellPadding = 0;
		tblCopyright.border      = 0;
		tblCopyright.align       = 'Center';
		tblCopyright.style.borderCollapse = 'collapse';
		divMainLayoutPanel.appendChild(tblCopyright);

		var trCopyright = document.createElement('tr');
		tblCopyright.appendChild(trCopyright);
		var tdCopyright = document.createElement('td');
		trCopyright.appendChild(tdCopyright);
		tdCopyright.className = 'copyRight';
		tdCopyright.align     = 'Center';
		txt = document.createTextNode('Copyright (C) 2005-2011 ');
		tdCopyright.appendChild(txt);

		var lnkSplendidCRM = document.createElement('a');
		lnkSplendidCRM.id        = 'lnkSplendidCRM';
		lnkSplendidCRM.className = 'copyRightLink';
		lnkSplendidCRM.href      = 'http://www.splendidcrm.com';
		lnkSplendidCRM.innerText = 'SplendidCRM Software, Inc.';
		lnkSplendidCRM.target    = '_blank';
		tdCopyright.appendChild(lnkSplendidCRM);
		txt = document.createTextNode(' All Rights Reserved.');
		tdCopyright.appendChild(txt);

		if ( txtUSER_NAME.value.length > 0 )
			txtPASSWORD.focus();
		else
			txtUSER_NAME.focus();
		callback(1, null);
	}
	catch(e)
	{
		callback(-1, SplendidError.FormatError(e, 'LoginViewUI_LoadView'));
	}
}

function LoginViewUI_Load(sLayoutPanel, sActionsPanel, cbLoginComplete, callback)
{
	try
	{
		LoginViewUI_Clear(sLayoutPanel, sActionsPanel, function(status, message)
		{
			if ( status == 1 )
			{
				LoginViewUI_LoadView(sLayoutPanel, sActionsPanel, cbLoginComplete, function(status, message)
				{
					if ( status == 1 )
					{
						callback(1, '');
					}
					else
					{
						callback(status, message);
					}
				});
			}
			else
			{
				callback(status, message);
			}
		});
	}
	catch(e)
	{
		callback(-1, SplendidError.FormatError(e, 'LoginViewUI_Load'));
	}
}


